#include "../include/BankSystem.hh"
#include "../include/SavingsAccount.hh"
#include "../include/CheckingAccount.hh"
#include "../include/Utils.hh"
#include <iostream>
#include <algorithm>
#include <limits>

BankSystem::BankSystem(AuthManager& auth)
    : authManager(auth), dataManager("data/") {
    // 在构造函数中加载数据
    loadData();
}

BankSystem::~BankSystem() {
    // 在析构函数中保存数据
    saveData();
}

bool BankSystem::saveData() {
    std::cout << "正在保存数据..." << std::endl;
    bool result = dataManager.saveAllData(customers, accounts, transactions);
    if (result) {
        std::cout << "数据保存成功！" << std::endl;
    } else {
        std::cout << "数据保存失败！" << std::endl;
    }
    return result;
}

bool BankSystem::loadData() {
    std::cout << "正在加载数据..." << std::endl;
    
    // 清空当前数据
    customers.clear();
    accounts.clear();
    transactions.clear();
    existingAccountIds.clear();
    
    // 加载数据
    bool result = dataManager.loadAllData(customers, accounts, transactions);
    
    // 重建existingAccountIds集合
    for (const auto& account : accounts) {
        existingAccountIds.insert(account->getAccountId());
    }
    
    if (result) {
        std::cout << "数据加载成功！" << std::endl;
        std::cout << "加载了 " << customers.size() << " 个客户，" 
                 << accounts.size() << " 个账户，" 
                 << transactions.size() << " 笔交易。" << std::endl;
    } else {
        std::cout << "数据加载失败或没有找到数据文件！" << std::endl;
    }
    return result;
}

bool BankSystem::registerCustomer(const std::string& name) {
    return registerCustomer(name, "000000"); // 使用默认密码
}

bool BankSystem::registerCustomer(const std::string& name, const std::string& password) {
    // 检查是否已有同名客户
    if (findCustomerByName(name) != nullptr) {
        std::cout << "错误：名为 " << name << " 的客户已存在。" << std::endl;
        return false;
    }
    
    // 检查密码是否为6位数字
    if (password.length() != 6 || !std::all_of(password.begin(), password.end(), ::isdigit)) {
        std::cout << "错误：密码必须为6位数字！" << std::endl;
        return false;
    }
    
    // 创建客户
    auto customer = std::make_shared<Customer>(name, password);
    customers.push_back(customer);
    
    // 为客户创建储蓄账户和支票账户
    createAccountsForCustomer(customer);
    
    return true;
}

std::shared_ptr<Customer> BankSystem::findCustomerByName(const std::string& name) const {
    auto it = std::find_if(customers.begin(), customers.end(),
                           [&name](const std::shared_ptr<Customer>& c) {
                               return c->getUsername() == name;
                           });
    
    if (it != customers.end()) {
        return *it;
    }
    
    return nullptr;
}

const std::vector<std::shared_ptr<Customer>>& BankSystem::getAllCustomers() const {
    return customers;
}

std::shared_ptr<Account> BankSystem::findAccountById(const std::string& accountId) const {
    auto it = std::find_if(accounts.begin(), accounts.end(),
                         [&accountId](const std::shared_ptr<Account>& a) {
                             return a->getAccountId() == accountId;
                         });
    
    if (it != accounts.end()) {
        return *it;
    }
    
    return nullptr;
}

const std::vector<std::shared_ptr<Account>>& BankSystem::getAllAccounts() const {
    return accounts;
}

void BankSystem::displayAllAccounts() const {
    std::cout << "===== 所有银行账户 =====" << std::endl << std::endl;
    
    std::cout << "储蓄账户:" << std::endl;
    int savingsCount = 0;
    for (const auto& account : accounts) {
        if (dynamic_cast<SavingsAccount*>(account.get())) {
            std::cout << ++savingsCount << ". ID: " << account->getAccountId() 
                     << "  |  持有人: " << account->getOwnerName()
                     << "  |  余额: ¥" << account->getBalance(Currency::CNY) << std::endl;
        }
    }
    
    std::cout << std::endl << "支票账户:" << std::endl;
    int checkingCount = 0;
    for (const auto& account : accounts) {
        if (dynamic_cast<CheckingAccount*>(account.get())) {
            std::cout << ++checkingCount << ". ID: " << account->getAccountId() 
                     << "  |  持有人: " << account->getOwnerName()
                     << "  |  余额: ¥" << account->getBalance(Currency::CNY) << std::endl;
        }
    }
    
    // 计算总账户数和总余额
    double totalBalance = 0.0;
    for (const auto& account : accounts) {
        totalBalance += account->getBalance(Currency::CNY);
    }
    
    std::cout << std::endl;
    std::cout << "总账户数: " << accounts.size() << std::endl;
    std::cout << "总客户数: " << customers.size() << std::endl;
    std::cout << "总余额: ¥" << totalBalance << std::endl;
}

bool BankSystem::deposit(const std::string& accountId, double amount, const std::string& note) {
    return deposit(accountId, amount, Currency::CNY, note);
}

bool BankSystem::deposit(const std::string& accountId, double amount, Currency currency, const std::string& note) {
    auto account = findAccountById(accountId);
    if (!account) {
        std::cout << "错误：账户 " << accountId << " 不存在。" << std::endl;
        return false;
    }
    
    bool success = account->deposit(amount, currency, note);
    if (success) {
        // 遍历交易历史，找到最新的交易记录并添加到系统交易记录中
        const auto& accountTransactions = account->getTransactionHistory();
        if (!accountTransactions.empty()) {
            // 在系统级别记录此交易
            addTransaction(accountTransactions.back());
        }
    }
    
    return success;
}

bool BankSystem::withdraw(const std::string& accountId, double amount, const std::string& note) {
    return withdraw(accountId, amount, Currency::CNY, note);
}

bool BankSystem::withdraw(const std::string& accountId, double amount, Currency currency, const std::string& note) {
    auto account = findAccountById(accountId);
    if (!account) {
        std::cout << "错误：账户 " << accountId << " 不存在。" << std::endl;
        return false;
    }
    
    bool success = account->withdraw(amount, currency, note);
    if (success) {
        // 遍历交易历史，找到最新的交易记录并添加到系统交易记录中
        const auto& accountTransactions = account->getTransactionHistory();
        if (!accountTransactions.empty()) {
            // 在系统级别记录此交易
            addTransaction(accountTransactions.back());
        }
    }
    
    return success;
}

bool BankSystem::transfer(const std::string& sourceAccountId, const std::string& destinationAccountId, 
                        double amount, const std::string& note) {
    return transfer(sourceAccountId, destinationAccountId, amount, Currency::CNY, note);
}

bool BankSystem::transfer(const std::string& sourceAccountId, const std::string& destinationAccountId, 
                        double amount, Currency currency, const std::string& note) {
    auto sourceAccount = findAccountById(sourceAccountId);
    if (!sourceAccount) {
        std::cout << "错误：源账户 " << sourceAccountId << " 不存在。" << std::endl;
        return false;
    }
    
    // 尝试精确匹配目标账户
    auto destinationAccount = findAccountById(destinationAccountId);
    
    // 如果精确匹配找不到，尝试部分匹配（只要账号包含输入的部分就算匹配）
    if (!destinationAccount) {
        for (const auto& account : accounts) {
            if (account->getAccountId().find(destinationAccountId) != std::string::npos) {
                destinationAccount = account;
                std::cout << "找到部分匹配账户: " << account->getAccountId() << std::endl;
                std::cout << "账户持有人: " << account->getOwnerName() << std::endl;
                std::cout << "是否使用此账户作为转账目标? (Y/N): ";
                char confirm;
                std::cin >> confirm;
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                
                if (toupper(confirm) == 'Y') {
                    break;
                } else {
                    destinationAccount = nullptr;
                }
            }
        }
    }
    
    if (!destinationAccount) {
        std::cout << "错误：目标账户 " << destinationAccountId << " 不存在。" << std::endl;
        std::cout << "可用账户列表：" << std::endl;
        int i = 1;
        for (const auto& account : accounts) {
            if (account->getAccountId() != sourceAccountId) { // 不显示源账户
                std::cout << i++ << ". " << account->getAccountId() << " (持有人: " << account->getOwnerName() << ")" << std::endl;
            }
        }
        return false;
    }
    
    bool success = sourceAccount->transfer(*destinationAccount, amount, currency, note);
    if (success) {
        // 遍历交易历史，找到最新的交易记录并添加到系统交易记录中
        const auto& accountTransactions = sourceAccount->getTransactionHistory();
        if (!accountTransactions.empty()) {
            // 在系统级别记录此交易
            addTransaction(accountTransactions.back());
        }
    }
    
    return success;
}

void BankSystem::addTransaction(const Transaction& transaction) {
    transactions.push_back(transaction);
}

const std::vector<Transaction>& BankSystem::getAllTransactions() const {
    return transactions;
}

std::vector<Transaction> BankSystem::getTransactionsByAccountId(const std::string& accountId) const {
    std::vector<Transaction> result;
    
    for (const auto& transaction : transactions) {
        if (transaction.sourceAccountId == accountId || transaction.destinationAccountId == accountId) {
            result.push_back(transaction);
        }
    }
    
    return result;
}

std::vector<Transaction> BankSystem::getTransactionsByCustomerName(const std::string& customerName) const {
    std::vector<Transaction> result;
    auto customer = findCustomerByName(customerName);
    
    if (!customer) {
        return result; // 客户不存在，返回空列表
    }
    
    // 获取该客户的所有账户ID
    std::vector<std::string> customerAccountIds;
    for (const auto& account : customer->getAccounts()) {
        customerAccountIds.push_back(account->getAccountId());
    }
    
    // 筛选该客户账户相关的所有交易
    for (const auto& transaction : transactions) {
        if (std::find(customerAccountIds.begin(), customerAccountIds.end(), transaction.sourceAccountId) != customerAccountIds.end() ||
            std::find(customerAccountIds.begin(), customerAccountIds.end(), transaction.destinationAccountId) != customerAccountIds.end()) {
            result.push_back(transaction);
        }
    }
    
    return result;
}

bool BankSystem::generateGlobalTransactionReport() const {
    return reportGenerator.generateGlobalTransactionReport(transactions);
}

bool BankSystem::generateCustomerReport(const std::string& customerName) const {
    auto customerTransactions = getTransactionsByCustomerName(customerName);
    return reportGenerator.generateCustomerReport(customerName, customerTransactions);
}

bool BankSystem::generateAccountReport(const std::string& accountId) const {
    auto accountTransactions = getTransactionsByAccountId(accountId);
    return reportGenerator.generateAccountReport(accountId, accountTransactions);
}

bool BankSystem::generateQuarterlyReport(int year, int quarter) const {
    return reportGenerator.generateQuarterlyReport(year, quarter, transactions);
}

std::string BankSystem::generateUniqueAccountId(const std::string& accountType) {
    std::string prefix;
    if (accountType == "savings") {
        prefix = "21"; // 储蓄账户前缀
    } else if (accountType == "checking") {
        prefix = "22"; // 支票账户前缀
    } else {
        std::cout << "错误：未知账户类型 " << accountType << std::endl;
        return "";
    }
    
    return Utils::generateUniqueAccountId(prefix, existingAccountIds);
}

void BankSystem::createAccountsForCustomer(std::shared_ptr<Customer> customer) {
    if (!customer) {
        std::cout << "错误：无法为空客户创建账户。" << std::endl;
        return;
    }
    
    // 创建储蓄账户
    std::string savingsId = generateUniqueAccountId("savings");
    auto savingsAccount = std::make_shared<SavingsAccount>(savingsId, customer->getUsername(), 0.0);
    
    // 创建支票账户
    std::string checkingId = generateUniqueAccountId("checking");
    auto checkingAccount = std::make_shared<CheckingAccount>(checkingId, customer->getUsername(), 0.0);
    
    // 将账户添加到客户和系统中
    customer->addAccount(savingsAccount);
    customer->addAccount(checkingAccount);
    
    accounts.push_back(savingsAccount);
    accounts.push_back(checkingAccount);
    
    std::cout << "已为客户 " << customer->getUsername() << " 创建以下账户:" << std::endl;
    std::cout << "- 储蓄账户: " << savingsId << std::endl;
    std::cout << "- 支票账户: " << checkingId << std::endl;
}

// 删除客户
bool BankSystem::deleteCustomer(const std::string& customerName, const std::string& password) {
    auto customer = findCustomerByName(customerName);
    if (!customer) {
        std::cout << "错误：客户 " << customerName << " 不存在。" << std::endl;
        return false;
    }
    
    // 验证密码
    if (!customer->verifyPassword(password)) {
        std::cout << "错误：密码不正确，无法删除客户。" << std::endl;
        return false;
    }
    
    // 检查客户的所有账户是否都已清空余额
    const auto& customerAccounts = customer->getAccounts();
    for (const auto& account : customerAccounts) {
        if (account->getBalance(Currency::CNY) > 0.01) { // 允许0.01以下的微小余额
            std::cout << "错误：客户 " << customerName << " 的账户 " << account->getAccountId() 
                      << " 仍有余额 ¥" << account->getBalance(Currency::CNY) << "，请先清空所有账户余额。" << std::endl;
            return false;
        }
    }
    
    // 从系统中删除客户的所有账户
    for (const auto& account : customerAccounts) {
        // 从账户列表中移除
        accounts.erase(
            std::remove_if(
                accounts.begin(), 
                accounts.end(),
                [&account](const std::shared_ptr<Account>& a) {
                    return a->getAccountId() == account->getAccountId();
                }
            ),
            accounts.end()
        );
        
        // 从已使用的账号ID集合中移除
        existingAccountIds.erase(account->getAccountId());
    }
    
    // 从客户列表中移除该客户
    customers.erase(
        std::remove_if(
            customers.begin(), 
            customers.end(),
            [&customerName](const std::shared_ptr<Customer>& c) {
                return c->getUsername() == customerName;
            }
        ),
        customers.end()
    );
    
    std::cout << "客户 " << customerName << " 及其所有账户已成功删除。" << std::endl;
    return true;
}

// 删除单个账户
bool BankSystem::deleteAccount(const std::string& accountId, const std::string& customerName, const std::string& password) {
    auto customer = findCustomerByName(customerName);
    if (!customer) {
        std::cout << "错误：客户 " << customerName << " 不存在。" << std::endl;
        return false;
    }
    
    // 确认删除操作（包括密码验证和账户余额检查）
    if (!customer->confirmDeleteAccount(accountId, password)) {
        return false;
    }
    
    auto account = findAccountById(accountId);
    if (!account) {
        std::cout << "错误：账户 " << accountId << " 不存在。" << std::endl;
        return false;
    }
    
    // 从账户列表中移除
    accounts.erase(
        std::remove_if(
            accounts.begin(), 
            accounts.end(),
            [&accountId](const std::shared_ptr<Account>& a) {
                return a->getAccountId() == accountId;
            }
        ),
        accounts.end()
    );
    
    // 从已使用的账号ID集合中移除
    existingAccountIds.erase(accountId);
    
    std::cout << "账户 " << accountId << " 已成功删除。" << std::endl;
    return true;
}

// 管理员删除账户
bool BankSystem::adminDeleteAccount(const std::string& accountId) {
    auto account = findAccountById(accountId);
    if (!account) {
        std::cout << "错误：账户 " << accountId << " 不存在。" << std::endl;
        return false;
    }
    
    // 管理员也不允许删除有余额的账户
    if (account->getBalance(Currency::CNY) > 0.01) {
        std::cout << "警告：账户 " << accountId << " 仍有余额 ¥" << account->getBalance(Currency::CNY) << std::endl;
        std::cout << "是否强制删除? (Y/N): ";
        char confirm;
        std::cin >> confirm;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        
        if (toupper(confirm) != 'Y') {
            std::cout << "删除操作已取消。" << std::endl;
            return false;
        }
    }
    
    // 所属客户名
    std::string ownerName = account->getOwnerName();
    
    // 从账户列表中移除
    accounts.erase(
        std::remove_if(
            accounts.begin(), 
            accounts.end(),
            [&accountId](const std::shared_ptr<Account>& a) {
                return a->getAccountId() == accountId;
            }
        ),
        accounts.end()
    );
    
    // 从已使用的账号ID集合中移除
    existingAccountIds.erase(accountId);
    
    std::cout << "管理员已删除账户 " << accountId << " (所属客户: " << ownerName << ")" << std::endl;
    return true;
} 